package com.xmtlxx.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.oms.domain.Property;
import com.xmtlxx.oms.domain.bo.PropertyBo;
import com.xmtlxx.oms.mapper.PropertyMapper;
import com.xmtlxx.wms.domain.Cabinet;
import com.xmtlxx.wms.domain.CabinetGroup;
import com.xmtlxx.wms.domain.Locator;
import com.xmtlxx.wms.domain.bo.LocatorBo;
import com.xmtlxx.wms.domain.bo.PutDtlBo;
import com.xmtlxx.wms.domain.vo.CabinetGroupVo;
import com.xmtlxx.wms.domain.vo.CabinetVo;
import com.xmtlxx.wms.domain.vo.LocatorVo;
import com.xmtlxx.wms.domain.vo.StoreAreaVo;
import com.xmtlxx.wms.mapper.*;
import com.xmtlxx.wms.service.ILocatorService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 库位Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class LocatorServiceImpl implements ILocatorService {

    private final LocatorMapper baseMapper;

    private final CabinetGroupMapper cabinetGroupMapper;

    private final CabinetMapper cabinetMapper;

    private final StoreAreaMapper storeAreaMapper;

    private final PropertyMapper propertyMapper;

    private final PutDtlMapper putDtlMapper;


    /**
     * 查询库位
     *
     * @param id 库位主键
     * @return 库位
     */
    @Override
    public LocatorVo queryById(String id){
        //return baseMapper.selectVoById(id);
        return baseMapper.selectLocatorVoByID(id);
    }

    /**
     * 查询库位列表
     *
     * @param bo 库位
     * @return 库位
     */
    @Override
    public TableDataInfo<LocatorVo> queryPageList(LocatorBo bo, PageQuery pageQuery) {
        Page<LocatorVo> result = baseMapper.selectPageLocatorList(pageQuery.build(), bo);
        if(result != null && result.getRecords() != null && result.getRecords().size() > 0 ){
            for (LocatorVo vo:result.getRecords()){
                if(bo.getMakeQrcode() != null && bo.getMakeQrcode() == 1){
                    String qrcode = makeQrcode(vo);
                    vo.setQrcode(qrcode);
                }

                /**
                 * 查询当前当前已上架物品
                 */
                if(bo.getShowProperites() != null && bo.getShowProperites() == 1) {
                    PropertyBo propertyBo = new PropertyBo();
                    propertyBo.setLocatorId(vo.getId());
                    propertyBo.setInventoryStatus("0");
                    vo.setPropertyVos(propertyMapper.selectPropertyList(propertyBo));
                }

                /**
                 * 查询当前已分配库位，但未上架的物品
                 */
                PutDtlBo putDtlBo = new PutDtlBo();
                putDtlBo.setLocatorId(vo.getId());
                putDtlBo.setStatus("0");
                putDtlBo.setDelFlag("0");
                vo.setPutDtlVos(putDtlMapper.selectPutDtlList(putDtlBo));

                vo.setIsPlan(false);
            }
        }
        return TableDataInfo.build(result);
    }

    public String makeQrcode(LocatorVo vo){
        //获取库区
        StoreAreaVo storeAreaVo =  storeAreaMapper.selectStoreAreaVoByID(vo.getAreaId());
        //获取货柜/车辆
        CabinetGroupVo cabinetGroupVo = cabinetGroupMapper.selectCabinetGroupVoByID(vo.getCabinetGroupId());

        //获取架子
        String cabintetNo = "";
        if(StringUtils.isNotEmpty(vo.getCabinetId())){
            CabinetVo cabinetVo = cabinetMapper.selectCabinetVoByID(vo.getCabinetId());
            cabintetNo = cabinetVo.getCno();
            vo.setCabinetName(cabinetVo.getName());
        }


        String qrcode = storeAreaVo.getAno()+"/"+cabinetGroupVo.getRegion()+"/"+ DateFormatUtils.format(new Date(), "yy/M")+"/";
        switch (storeAreaVo.getAno()){
            case "CL":
                qrcode += cabinetGroupVo.getCno()+"/"+"1"+"/"+vo.getName();
                break;
            case "PT":
                if(StringUtils.isNotEmpty(vo.getShape())){
                    qrcode += vo.getShape()+"/";
                }
//                qrcode += cabinetGroupVo.getCno()+"/"+cabintetNo+"/"+(vo.getFloors() != null?vo.getFloors()+"/":"")+vo.getBoxs()+"/";
                qrcode += cabinetGroupVo.getCno()+"/"+cabintetNo+"/"+(vo.getFloors() != null?vo.getFloors()+"/":"");
                if(StringUtils.isNotEmpty(vo.getShape()) && vo.getShape().equals("X1")){
                    qrcode += vo.getBoxs()+"/";
                }
                break;
            case "GZ":
                qrcode += cabinetGroupVo.getCno()+"/"+vo.getName()+"/";
                break;
            case "DZ":
                qrcode += cabinetGroupVo.getCno()+"/"+vo.getName()+"/";
                break;
            case "ZX":
                if(vo.getFloors() != null){
                    qrcode += vo.getFloors()+"/";
                }else {
                    qrcode = qrcode;
                }

                break;
            case "DX":
                qrcode = qrcode;
                break;
            case "JL":
                qrcode += cabinetGroupVo.getCno()+"/"+vo.getName()+"/";
            default:
                break;
        }
        return qrcode;
    }

    /**
     * 查询库位列表
     *
     * @param bo 库位
     * @return 库位
     */
    @Override
    public List<LocatorVo> queryList(LocatorBo bo) {
       // LambdaQueryWrapper<Locator> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectLocatorList(bo);
    }

    private LambdaQueryWrapper<Locator> buildQueryWrapper(LocatorBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getAreaId()), Locator::getAreaId, bo.getAreaId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), Locator::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), Locator::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), Locator::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增库位
     *
     * @param bo 库位
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(LocatorBo bo) {
        Locator add = BeanUtil.toBean(bo, Locator.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");

        add.setShape(StringUtils.join(bo.getShapeList(),","));

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
            Long totals = 0l;
            if(StringUtils.isNotBlank(add.getCabinetGroupId())){
                lqw.eq(Locator::getCabinetGroupId,add.getCabinetGroupId());
                totals = baseMapper.selectCount(lqw);
                CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(add.getCabinetGroupId());
                cabinetGroup.setLnums(totals);
                cabinetGroupMapper.updateById(cabinetGroup);
            }
            if(StringUtils.isNotBlank(add.getCabinetId())){
                lqw.eq(Locator::getCabinetId,add.getCabinetId());
                totals = baseMapper.selectCount(lqw);
                Cabinet cabinet = cabinetMapper.selectById(add.getCabinetId());
                cabinet.setLnums(totals);
                cabinetMapper.updateById(cabinet);
            }
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertBatchByVo(LocatorVo vo) {
        CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(vo.getCabinetGroupId());
        Integer lnums  = cabinetGroup.getLnums() == null ? 1 : cabinetGroup.getLnums().intValue() + 1;
        Integer seq = vo.getSeq() != null ? vo.getSeq() : lnums;
        for(int i = vo.getStartNo();i<=vo.getEndNo();i++){
            Locator add = new Locator();
            add.setId(IdUtil.simpleUUID());
            add.setDelFlag("0");
            add.setStatus("0");
            add.setCabinetGroupId(vo.getCabinetGroupId());
            add.setStoreId(cabinetGroup.getStoreId());
            add.setAreaId(cabinetGroup.getAreaId());
            add.setRegion(cabinetGroup.getRegion());
            add.setName(vo.getName()+i);
            add.setPnums(0l);
            add.setSeq(seq);
            add.setAisleCode(lnums+"");
            baseMapper.insert(add);
            seq ++;
            lnums++;
        }
        return true;
    }

    @Override
    public String insertBatchLocatorByVo(LocatorVo vo) {
        Cabinet cabinet = cabinetMapper.selectById(vo.getCabinetId());
        CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(cabinet.getGroupId());
        Integer lnums  = cabinetGroup.getLnums() == null ? 1 : cabinetGroup.getLnums().intValue() + 1;
        Integer seq = vo.getSeq() != null ? vo.getSeq() : lnums;
        for(int f = vo.getStartFloor();f <= vo.getEndFloor();f++){
            for(int i = vo.getStartNo();i<=vo.getEndNo();i++){
                Locator add = new Locator();
                add.setId(IdUtil.simpleUUID());
                add.setDelFlag("0");
                add.setStatus("0");
                add.setCabinetGroupId(cabinet.getGroupId());
                add.setStoreId(cabinetGroup.getStoreId());
                add.setAreaId(cabinetGroup.getAreaId());
                add.setRegion(cabinetGroup.getRegion());
                add.setBoxs(i);
                add.setName("第"+f+"层"+i+"号箱");
                add.setPnums(0l);
                add.setSeq(seq);
                add.setFloors(f);
                add.setAisleCode(lnums+"");
                add.setCabinetId(vo.getCabinetId());
                baseMapper.insert(add);
                seq ++;
                lnums++;
            }
        }
        LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
        lqw.eq(Locator::getCabinetId,vo.getCabinetId());
        Long totals = baseMapper.selectCount(lqw);
        cabinet.setLnums(totals);
        cabinetMapper.updateById(cabinet);
        return cabinet.getGroupId();
    }

    @Override
    public Boolean planBatchLocatorByVo(LocatorVo vo) {
        List<Locator> locatorList = new ArrayList<>();
        if(vo.getLocatorIds() != null && vo.getLocatorIds().size() > 0){
            locatorList = vo.getLocatorIds().stream().map(locatorId->{
                Locator locator = baseMapper.selectById(locatorId);
                locator.setCabinetId(vo.getCabinetId());
                return locator;
            }).collect(Collectors.toList());
        }

        return  baseMapper.updateBatchById(locatorList);
    }

    @Override
    public void countLocators(String cabinetGroupId) {
        LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
        lqw.eq(Locator::getCabinetGroupId,cabinetGroupId);
        long totals = baseMapper.selectCount(lqw);
        CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(cabinetGroupId);
        cabinetGroup.setLnums(totals);
        cabinetGroupMapper.updateById(cabinetGroup);
    }

    @Override
    public Long insertByWithBo(List<LocatorBo> boList,String groupId) {
        List<Locator> adds = new ArrayList<>();
        adds = boList.stream().map(item->{
            Locator add = baseMapper.selectOne(new LambdaQueryWrapper<Locator>().eq(Locator::getCabinetAisleRelaId,item.getCabinetAisleRelaId())
                .eq(Locator::getCabinetGroupId,groupId)
            );
            if(add == null){
                add = BeanUtil.toBean(item, Locator.class);
                validEntityBeforeSave(add);
                add.setId(IdUtil.simpleUUID());
                add.setDelFlag("0");
                add.setStatus("0");
                add.setCabinetGroupId(groupId);
            }else {
                BeanUtil.copyProperties(item,add,"id");
            }
            return add;
        }).collect(Collectors.toList());
        boolean flag = baseMapper.insertOrUpdateBatch(adds);
        if(flag){
            return baseMapper.selectCount(new LambdaQueryWrapper<Locator>().eq(Locator::getCabinetGroupId,groupId));
        }
        return 0l;
    }

    /**
     * 修改库位
     *
     * @param bo 库位
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(LocatorBo bo) {
        Locator update = BeanUtil.toBean(bo, Locator.class);
        validEntityBeforeSave(update);
        boolean flag = baseMapper.updateById(update) > 0;
        if(flag){
            LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
            Long totals = 0l;
            if(StringUtils.isNotBlank(update.getCabinetGroupId())){
                lqw.eq(Locator::getCabinetGroupId,update.getCabinetGroupId());
                totals = baseMapper.selectCount(lqw);
                CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(update.getCabinetGroupId());
                cabinetGroup.setLnums(totals);
                cabinetGroupMapper.updateById(cabinetGroup);
            }
            if(StringUtils.isNotBlank(update.getCabinetId())){
                lqw.eq(Locator::getCabinetId,update.getCabinetId());
                totals = baseMapper.selectCount(lqw);
                Cabinet cabinet = cabinetMapper.selectById(update.getCabinetId());
                cabinet.setLnums(totals);
                cabinetMapper.updateById(cabinet);
            }
        }
        return flag;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Locator entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除库位
     *
     * @param ids 需要删除的库位主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        for (String id :ids){
            Locator update = baseMapper.selectById(id);
            LambdaQueryWrapper<Locator> lqw = Wrappers.lambdaQuery();
            Long totals = 0l;
            if(StringUtils.isNotBlank(update.getCabinetGroupId())){
                lqw.eq(Locator::getCabinetGroupId,update.getCabinetGroupId());
                totals = baseMapper.selectCount(lqw) -1;
                CabinetGroup cabinetGroup = cabinetGroupMapper.selectById(update.getCabinetGroupId());
                cabinetGroup.setLnums(totals);
                cabinetGroupMapper.updateById(cabinetGroup);
            }
            if(StringUtils.isNotBlank(update.getCabinetId())){
                lqw.eq(Locator::getCabinetId,update.getCabinetId());
                totals = baseMapper.selectCount(lqw) -1;
                Cabinet cabinet = cabinetMapper.selectById(update.getCabinetId());
                cabinet.setLnums(totals);
                cabinetMapper.updateById(cabinet);
            }
        }
        return  baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean autoUpdateDZCabinetGroup() {
        List<CabinetGroup> groups = cabinetGroupMapper.selectList(new LambdaQueryWrapper<CabinetGroup>().eq(CabinetGroup::getCabinetType,"0").eq(CabinetGroup::getAreaId,"e23c56cd41d041e9afe79158400fb8dc"));
        for (CabinetGroup group : groups){
            //架子数
            List<Cabinet> cabinets = cabinetMapper.selectList(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getGroupId,group.getId()).orderByAsc(Cabinet::getSeq));
            List<Locator> locators = baseMapper.selectList(new LambdaQueryWrapper<Locator>().eq(Locator::getCabinetGroupId,group.getId()).orderByAsc(Locator::getSeq));
            int j = 0;//最大值10
            int tols = 3;
            for(Locator locator : locators){
                if(locators.size() == 223){
                    tols = 3;
                    if(locator.getSeq() > 3 && locator.getSeq() <=23){
                        j = 1;
                        tols = 20;
                    }else if(locator.getSeq() > 23 && locator.getSeq() <=43){
                        j = 2;
                        tols = 20;
                    }else if(locator.getSeq() > 43 && locator.getSeq() <=63){
                        j = 3;
                        tols = 20;
                    }else if(locator.getSeq() > 63 && locator.getSeq() <=83){
                        j = 4;
                        tols = 20;
                    }else if(locator.getSeq() > 83 && locator.getSeq() <=103){
                        j = 5;
                        tols = 20;
                    }else if(locator.getSeq() > 103 && locator.getSeq() <=123){
                        j = 6;
                        tols = 20;
                    }else if(locator.getSeq() > 123 && locator.getSeq() <=143){
                        j = 7;
                        tols = 20;
                    }else if(locator.getSeq() > 143 && locator.getSeq() <=163){
                        j = 8;
                        tols = 20;
                    }else if(locator.getSeq() > 163 && locator.getSeq() <=183){
                        j = 9;
                        tols = 20;
                    }else if(locator.getSeq() > 183 && locator.getSeq() <=203){
                        j = 10;
                        tols = 20;
                    }else if(locator.getSeq() > 203 && locator.getSeq() <=223){
                        j = 11;
                        tols = 20;
                    }
                }else if(locators.size() == 112){
                    tols = 2;
                    if(locator.getSeq() > 2 && locator.getSeq() <=12){
                        j = 1;
                        tols = 10;
                    }else if(locator.getSeq() > 12 && locator.getSeq() <=22){
                        j = 2;
                        tols = 10;
                    }else if(locator.getSeq() > 22 && locator.getSeq() <=32){
                        j = 3;
                        tols = 10;
                    }else if(locator.getSeq() > 32 && locator.getSeq() <=42){
                        j = 4;
                        tols = 10;
                    }else if(locator.getSeq() > 42 && locator.getSeq() <=52){
                        j = 5;
                        tols = 10;
                    }else if(locator.getSeq() > 52 && locator.getSeq() <=62){
                        j = 6;
                        tols = 10;
                    }else if(locator.getSeq() > 62 && locator.getSeq() <=72){
                        j = 7;
                        tols = 10;
                    }else if(locator.getSeq() > 72 && locator.getSeq() <=82){
                        j = 8;
                        tols = 10;
                    }else if(locator.getSeq() > 82 && locator.getSeq() <=92){
                        j = 9;
                        tols = 10;
                    }else if(locator.getSeq() > 92 && locator.getSeq() <=102){
                        j = 10;
                        tols = 10;
                    }else if(locator.getSeq() > 102 && locator.getSeq() <=112){
                        j = 11;
                        tols = 10;
                    }
                }
                Cabinet cabinet = cabinets.get(j);
                cabinet.setLnums(Long.valueOf(tols));
                cabinetMapper.updateById(cabinet);
                locator.setCabinetId(cabinets.get(j).getId());
                baseMapper.updateById(locator);
            }
        }

        return true;
    }

    public Long getPropertyNums(String key) {
        long result = 0l;
        LambdaQueryWrapper<Property> lqw = Wrappers.lambdaQuery();
        List<String> keys = Arrays.asList(key.split("/"));
        if(keys.get(0).equals("CL")){
            String carkey = keys.get(keys.size()-1);
            result = Long.parseLong(carkey.replaceAll("\\D+",""));
        }else {
            lqw.like(Property::getQrcode,key);
            result = propertyMapper.selectCount(lqw);
            result = result+1;
        }

        return result;
    }
}
